
package Pages;

import java.net.*;
import java.awt.*;
import java.awt.List;
import java.io.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.swing.*;
import javax.imageio.*;
import java.net.MalformedURLException;
import java.net.URL;
import javax.net.ssl.SSLSocketFactory;

import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.*;
import org.apache.http.client.entity.*;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.entity.mime.*;
import org.apache.http.entity.mime.content.*;
import org.apache.http.impl.client.*;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.*;
import org.apache.http.params.*;
import org.apache.http.protocol.*;
import org.apache.http.util.EntityUtils;

import Tools.stopwatch;
import clientMain.*;

/**
 * Implements a General Page Type, specific pages are extended from this
 * @author Andrew Fox
 *
 */


public class Page {
	StringBuffer url;
	StringBuffer html;
	String pageType;
	StringBuffer lastURL;
	Client client;
	boolean verbose=runSettings.verbose;
	boolean HTML4=runSettings.HTML4;
	double initialThinkTime=500;
	long pageOpenTime=0;
	long responseTime;
	ArrayList<Image>images=new ArrayList<Image>();
	int activeConnections=0;
	//	Socket sock=client.sock;

	public Page(StringBuffer url, StringBuffer lastURL, Client client){
		this.url=url;
		this.lastURL=lastURL;
		if (!url.toString().startsWith("<HTML>")){
			this.html=openURL(url,client);
		}
		else{
			this.html=url;
		}
		pageOpenTime=new Date().getTime();
		this.pageType=getPageType();
		if (verbose)System.out.println("User: "+client.userInfo.username+" - Page Type: "+this.pageType);
		this.client=client;
	}

	public Page(StringBuffer url,StringBuffer html,Client client, String pageType){
		this.url=url;
		this.html=html;
		this.client=client;
		this.pageType=pageType;
	}

	/**
	 * Determines what type of page the page is
	 * @return The page type
	 */
	public String getPageType(){
		String pageType=null;

		if(HTML4==true){
			int start=html.indexOf("<TITLE>")+("<TITLE>").length();
			int end=html.indexOf("</TITLE>",start);

			String title=html.substring(start,end);

			if (title.equals("Login"))
				pageType="login";
			if (title.equals("My Account"))
				pageType="userHome";
			if(title.equals("Update User Details"))
				pageType="updateUser";
			if(title.equals("Register User"))
				pageType="registerUser";
			if(title.equals("Sell Item"))
				pageType="sellItem";
			if(title.equals("Bid Confirmed"))
				pageType="bidConfirm";
			if(title.equals("Sell Item Confirmed"))
				pageType="sellConfirm";
			if(title.equals("Browse Category"))
				pageType="browseCategory";
			if(title.equals("View Item"))
				pageType="item";
			if(title.equals("Buy Item"))
				pageType="buyItem";
			if(title.equals("Upload images"))
				pageType="uploadImages";
			if(title.equals("View User"))
				pageType="viewUser";
			if(title.equals("Confirm Buy"))
				pageType="confirmBuy";
			if(title.equals("Logout"))
				pageType="logout";
		}
		else{
			int start=runSettings.appURL.length()+1;
			int end=url.indexOf("?",start);
			if (end==-1)
				end=url.length();
			String title=url.substring(start,end);
			if (title.equals("login"))
				pageType="login";
			if (title.equals("myaccount"))
				pageType="userHome";
			if(title.equals("updateuserdetails"))
				pageType="updateUser";
			if(title.equals("registeruser"))
				pageType="registerUser";
			if(title.equals("sellitem"))
				pageType="sellItem";
			if(title.equals("bid"))
				pageType="bidConfirm";
			if(title.equals("Sell Item Confirmed"))
				pageType="sellConfirm";
			if(title.equals("browsecategory"))
				pageType="browseCategory";
			if(title.equals("viewitem"))
				pageType="item";
			if(title.equals("buyitem"))
				pageType="buyItem";
			if(title.equals("Upload images"))
				pageType="uploadImages";
			if(title.equals("View User"))
				pageType="viewUser";
			if(title.equals("Confirm Buy"))
				pageType="confirmBuy";
			if(title.equals("Logout"))
				pageType="logout";
			if(title.equals("index.html"))
				pageType="HTML5HomePage";
		}

		return pageType;
	}

	/**
	 * Converts the general page to the specific page type
	 * @return Specific Page
	 */
	public Page toPageType(){
		Page pageToReturn=null;
		if (pageType=="login")
			pageToReturn= new LoginPage(this);
		else if(pageType=="registerUser")
			pageToReturn=new RegisterUserPage(this);
		else if(pageType=="item")
			pageToReturn=new ItemPage(this);
		else if(pageType=="userHome")
			pageToReturn=new UserHomePage(this);
		else if(pageType=="updateUser")
			pageToReturn=new UpdateUserPage(this);
		else if(pageType=="sellItem")
			pageToReturn=new SellItemPage(this);
		else if(pageType=="bidConfirm")
			pageToReturn=new BidConfirmPage(this);
		else if(pageType=="sellConfirm")
			pageToReturn=new SellItemConfirmPage(this);
		else if(pageType=="browseCategory")
			pageToReturn=new BrowsePage(this);
		else if(pageType=="buyItem")
			pageToReturn=new BuyItemPage(this);
		else if(pageType=="uploadImages")
			pageToReturn=new UploadImagesPage(this);
		else if(pageType=="viewUser")
			pageToReturn=new ViewUserPage(this);
		else if(pageType=="confirmBuy")
			pageToReturn=new ConfirmBuyPage(this);
		else if(pageType=="logout")
			pageToReturn=new LogOutPage(this);
		else if(pageType=="HTML5HomePage")
			pageToReturn=new HTML5HomePage(this);

		return pageToReturn;
	}

	/**
	 * Opens a URL and returns the HTML code of the page
	 * @param urlString - URL to be opened
	 * @return html - HTML of the page
	 */
	public synchronized StringBuffer openURL(StringBuffer urlString, Client client){
		StringBuffer ret = new StringBuffer();
		//		if (urlString.indexOf("?")!=-1){
		//			StringBuffer content=new StringBuffer(urlString.subSequence(urlString.indexOf("?")+1, urlString.length()));
		//			urlString.delete(urlString.indexOf("?")+1, urlString.length());
		//			do{
		//				int eqIndex=content.indexOf("=");
		//				int andIndex=content.indexOf("&");
		//				boolean addAnd=true;
		//				if (andIndex==-1){
		//					andIndex=content.length();
		//					addAnd=false;
		//				}
		//				try {
		//					urlString.append(URLEncoder.encode(content.substring(0, eqIndex), "UTF-8")).append("=").append(URLEncoder.encode(content.substring(eqIndex+1, andIndex), "UTF-8"));
		//				} catch (UnsupportedEncodingException e) {
		//					// TODO Auto-generated catch block
		//					e.printStackTrace();
		//				}
		//				if (addAnd==true){
		//					urlString.append("&");
		//					content.delete(0, andIndex+1);
		//				}
		//				else
		//				content.delete(0, andIndex);
		//			}while(content.length()>0);
		//		}

		System.out.println("URLSTRING "+urlString);
		try{
			//	URL url = new URL(urlString);
			Socket socket=new Socket("cmubisapp3.arcanine.lan",8080);
			System.out.println("LOCAL PORT: "+socket.getLocalPort());

			stopwatch sw=new stopwatch();
			//	BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
			PrintStream out=new PrintStream(socket.getOutputStream());
			out.println("GET " + urlString + " HTTP/1.0\n");
			out.flush();

			BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));


			if(br.read()!=-1){
				do{
					ret.append(br.readLine());
				}while(ret.indexOf("</HTML>")==-1);
			}
			sw.pause();
			ret.delete(0, ret.indexOf("<HTML>"));
			// find image links
			int end=ret.indexOf(".jpg\"")+".jpg".length();
			int start=ret.lastIndexOf("\"../",end)+"\"../".length();
			while(end!=".jpg".length()-1){
				getImage gI=new getImage(ret.substring(start,end));
				addConnection();
				sw.start();
				//gI.start();
				if (getConnectionCount()==0)
					sw.pause();
				end=ret.indexOf(".jpg\"",end)+".jpg".length();
				start=ret.lastIndexOf("\"../",end)+"\"../".length();
			}
			while(getConnectionCount()>0){wait();}this.responseTime=sw.stop();
			clientGenerator.stats.activeHistogram.add(responseTime);
			out.close();
			br.close();

		}
		catch(Exception e){}	
		System.out.println("RET: "+ret);
		return ret;
	}

	public String createURL(HashMap<String, StringBuffer> data) throws UnsupportedEncodingException{
		Set keys = data.keySet();
		Iterator keyIter = keys.iterator();
		String content = "";
		for(int i=0; keyIter.hasNext(); i++) {
			Object key = keyIter.next();
			if(i!=0) {
				content += "&";
			}
			content += key + "=" + URLEncoder.encode(data.get(key).toString(), "UTF-8");
		}
		return content;
	}

	//	public String doSubmit(String url, HashMap<String, String> data) throws Exception {	
	//		URL siteUrl = new URL(url);
	//		HttpURLConnection conn = (HttpURLConnection) siteUrl.openConnection();
	//		conn.setRequestMethod("POST");
	//		conn.setDoOutput(true);
	//		conn.setDoInput(true);
	//		Set keys = data.keySet();
	//		Iterator keyIter = keys.iterator();
	//		String content = "";
	//		for(int i=0; keyIter.hasNext(); i++) {
	//			Object key = keyIter.next();
	//			if(i!=0) {
	//				content += "&";
	//			}
	//			content += key + "=" + URLEncoder.encode(data.get(key), "UTF-8");
	//		}
	//
	//		DataOutputStream out = new DataOutputStream(conn.getOutputStream());
	//		if(verbose)System.out.println(content);
	//		out.writeBytes(content);
	//		out.flush();
	//		out.close();
	//
	//
	//
	//		String line = "";
	//
	//		try{
	//			BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
	//
	//			while(!(line=line.concat(in.readLine())).endsWith("</HTML>")){}
	//			if(verbose)System.out.println(line);
	//			in.close();
	//		}
	//		catch(java.io.IOException e){
	//			int start=e.toString().indexOf("http://");
	//			line=openURL(e.toString().substring(start).replace(" ", "%20"));
	//		}
	//
	//		return line;
	//	}

	/**
	 * Gets Form Data from the page being viewed
	 * @return data - HashMap of form names and values
	 */
	public HashMap<String, StringBuffer> getFormData(){
		String name;
		StringBuffer value=new StringBuffer();
		HashMap<String, StringBuffer>data=new HashMap<String,StringBuffer>();
		int start=html.indexOf("POST");
		start=html.indexOf(" name=\"",start)+(" name=\"").length();

		int end=start;
		int formEnd=html.indexOf("</form>");
		while(start<formEnd&&start!=(" name=\"").length()-1){
			end=html.indexOf("\"",start);
			name=html.substring(start,end);
			if (html.charAt(end+1)=='>'){
				end=html.indexOf("\" SELECTED");
				start=html.lastIndexOf("value=\"",end)+("value=\"").length();
			}
			else{
				start=html.indexOf("value=\"",end)+("value=\"").length();
				end=html.indexOf("\"",start);
			}
			if(name.startsWith("image")==false){
				value=new StringBuffer(html.subSequence(start,end));
				start=html.indexOf(" name=\"",start)+(" name=\"").length();

				data.put(name,value);
			}


		}
		return data;
	}

	/**
	 * Gets the number of words in a string
	 * @param str - The string
	 * @return numWords - number of words in str
	 */
	public int getNumWords(StringBuffer str){
		int numWords=0;
		int index=str.length();
		while(index>0){
			index=str.lastIndexOf(" ",index);
			index-=1;
			numWords++;
		}
		return numWords;
	}

	/**
	 * Determines if a typing error is made in an entry, and makes the error by adding a "1" to the end of the string
	 * Error is based on the typing error rate of the client
	 * @param str - String to be error tested on
	 * @return Returns the string sent in - with or without the error as determined
	 */
	public StringBuffer typingError(StringBuffer str){
		int numWords=getNumWords(str);
		//double everythingRight=Math.pow(1-client.typingErrorRate, numWords);
		double everythingRight=1;
		if (Math.random()>everythingRight){
			int charToReplace=(int)(Math.random()*str.length());
			str=str.replace(charToReplace,charToReplace+1,"a");
			if (verbose)System.out.println("User: "+client.userInfo.username+" - Typing Error Made");
		}
		return str;
	}

	/**
	 * Converts a string of specified formatting to a date
	 * @param s - String
	 * @return date- string converted to a date
	 */
	public Date StringToDate(String s){
		Date date=null;
		DateFormat df =new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
		try{
			date=df.parse(s);
		}catch(ParseException e){
			e.printStackTrace();
		}
		return date;
	}

	/**
	 * POSTS data and submits it to a form
	 * @param url - URL of the form
	 * @param data - data to be POSTed
	 * @param formName - name of the form
	 * @return Returns the page returned after form submission
	 * @throws org.apache.http.ParseException
	 * @throws ClientProtocolException
	 * @throws IOException
	 * @throws URISyntaxException
	 * @throws InterruptedException 
	 */
	public synchronized String doSubmit2(String url,HashMap<String, String> data,String formName) throws org.apache.http.ParseException, ClientProtocolException, IOException, URISyntaxException, InterruptedException{
		url=runSettings.appURL+"/"+formName;
		String toReturn="";
		if(verbose)System.out.println("URL: "+ url);
		//URI formURL=new URI(url,action);
		HttpClient client = new DefaultHttpClient();
		HttpGet httpget = new HttpGet(url);
		HttpPost  post   = new HttpPost( url);
		HttpContext localContext = new BasicHttpContext();

		ArrayList<NameValuePair> formparams = new ArrayList<NameValuePair>();
		for (String m:data.keySet()){
			formparams.add(new BasicNameValuePair(m, data.get(m)));
		}
		UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");

		post.setEntity(entity);

		HttpResponse response = client.execute(post,localContext);



		InputStream result=null;

		org.apache.http.Header locationHeader=response.getFirstHeader("Location");
		if (locationHeader != null) {
			//			httpget = new HttpGet(locationHeader.getValue());
			//			response=getThreadSafeClient().execute(httpget);
			toReturn=locationHeader.getValue().replace(" ", "%20");
		}
		else{
			result = response.getEntity().getContent();
			stopwatch sw=new stopwatch();
			BufferedReader br = new BufferedReader(new InputStreamReader(result));

			if(br.read()!=-1){
				do{
					toReturn = toReturn.concat(br.readLine());
				}while(!toReturn.endsWith("</HTML>"));
				sw.pause();
				// find image links
				int end=toReturn.indexOf(".jpg\"")+".jpg".length();
				int start=toReturn.lastIndexOf("\"../",end)+"\"../".length();
				while(end!=".jpg".length()-1){
					getImage gI=new getImage(toReturn.substring(start,end));
					addConnection();
					sw.start();
					gI.start();
					if (getConnectionCount()==0)
						sw.pause();
					end=toReturn.indexOf(".jpg\"",end)+".jpg".length();
					start=toReturn.lastIndexOf("\"../",end)+"\"../".length();
				}
				while(getConnectionCount()>0){wait();}this.responseTime=sw.stop();
				clientGenerator.stats.activeHistogram.add(responseTime);
			}
			client.getConnectionManager().shutdown();
			result.close();
		}


		return toReturn;
	}

	public synchronized StringBuffer doSubmit3(StringBuffer url,HashMap<String, StringBuffer> data,Client client) throws UnsupportedEncodingException, IOException{

		Set keys = data.keySet();
		Iterator keyIter = keys.iterator();
		String content = "";
		for(int i=0; keyIter.hasNext(); i++) {
			Object key = keyIter.next();
			if(i!=0) {
				content += "&";
			}
			content += key + "=" + URLEncoder.encode(data.get(key).toString(), "UTF-8");
		}



		String data2 = URLEncoder.encode("key1", "UTF-8") + "=" + URLEncoder.encode("value1", "UTF-8");

		Socket socket = new Socket("10.9.77.3", 8080);
		System.out.println("LOCAL PORT: "+socket.getLocalPort());
		//		if (client.sock.isClosed()){
		//			client.sock=new Socket("10.9.77.3",8080,InetAddress.getLocalHost(),client.localPort);
		//		}
		//Socket socket=client.sock;
		StringBuffer output=new StringBuffer();
		BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF8"));
		output.append("POST ").append(url).append(" HTTP/1.0\r\n");
		output.append("Content-Length: ").append(content.length()).append("\r\n");
		output.append("Content-Type: application/x-www-form-urlencoded\r\n");
		output.append("\r\n");
		output.append(content);
		System.out.println(output);
		wr.write(output.toString());
		wr.flush();

		BufferedReader rd = new BufferedReader(new InputStreamReader(socket.getInputStream()));

		StringBuffer line=new StringBuffer();
		StringBuffer newLine=new StringBuffer();
		boolean redirect=false;
		String location="";
		while ((newLine=new StringBuffer(rd.readLine())).indexOf("</HTML>")==-1) {
			line.append(newLine);
			//	System.out.println(line+"   "+redirect);
			if (line.indexOf("HTTP/1.1 302 Moved Temporarily")!=-1)
				redirect=true;
			if(redirect==true&&line.indexOf("Location: http")!=-1){
				location=line.substring(line.indexOf("Location: ")+("Location: ").length());
				break;
			}
		}
		line.append(newLine);
		//		if(rd.read()!=-1){
		//			do{
		//				line = line.concat(rd.readLine());
		//				if (line.contains("HTTP/1.1 302 Moved Temporarily"))
		//					redirect=true;
		//				if(redirect==true&&line.contains("Location: http")){
		//					location=line.substring(line.indexOf("Location: ")+("Location: ").length());
		//					break;
		//				}
		//			}while(!line.endsWith("</HTML>"));
		//		}

		if (redirect==true){
			System.out.println("LOCATION: "+location);
			System.out.println(location.substring(location.indexOf(runSettings.hostURL.toString())+runSettings.hostURL.length()));
			line=doSubmit4(null,location.substring(location.indexOf(runSettings.hostURL.toString())+runSettings.hostURL.length()).replace(" ", "%20"),null,client);
			line.delete(0, line.indexOf("<HTML>"));
		}
		System.out.println("DOSUBMIT3 RET: "+line);
		//	    wr.close();
		//	    rd.close();
		socket.close();
		return line;
		//return ret;
	}

	public StringBuffer doSubmit4(StringBuffer url,String content,String formName,Client client) throws UnsupportedEncodingException, IOException{
		Socket socket = new Socket("10.9.77.3", 8080);
		System.out.println("LOCAL PORT: "+socket.getLocalPort());
		PrintStream out=new PrintStream(socket.getOutputStream());
		out.println("GET " + content + " HTTP/1.0\n");
		out.flush();
		BufferedReader rd = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		//	    String line;
		//	    while ((line = rd.readLine()) != null) {
		//	      System.out.println(line);
		//	    }
		StringBuffer line=new StringBuffer();
		if(rd.read()!=-1){
			do{
				line.append(rd.readLine());
			}while(line.indexOf("</HTML>")==-1&&line!=null);
		}
		socket.close();
		return line;
	}

	public synchronized StringBuffer doSubmitPic2(String url,HashMap<String, StringBuffer> data,ArrayList<File> pics) throws org.apache.http.ParseException, ClientProtocolException, IOException, InterruptedException{

		ArrayList<String> imgCont=new ArrayList<String>();
		StringBuffer header=new StringBuffer();
		StringBuffer body=new StringBuffer();
		Socket socket = new Socket("10.9.77.3", 8080);
		System.out.println("LOCAL PORT: "+socket.getLocalPort());
		StringBuffer boundary=new StringBuffer("----WebKitFormBoundarydz41Pw6LXtRaD3BW");
		StringBuffer twoHyph=new StringBuffer("--");
		OutputStream os=socket.getOutputStream();

		header.append("POST ").append(url).append(" HTTP/1.0\r\n");
		header.append("Content-Type: multipart/form-data; boundary=").append(boundary).append("\r\n");
		//	header.append("Connection: keep-alive\r\n");


		for(String m:data.keySet()){
			body.append(twoHyph).append(boundary).append("\r\n");

			body.append("Content-Disposition: form-data; name=\"").append(m).append("\"\r\n\r\n");
			body.append(data.get(m)).append("\r\n");

		}
		body.append(twoHyph).append(boundary).append("\r\n");
		ArrayList<byte[]>imgData=new ArrayList<byte[]>();
		for (int i=0;i<pics.size();i++){
			StringBuffer buf=new StringBuffer();
			InputStream imgIs=new FileInputStream(pics.get(i));
			imgData.add(new byte[imgIs.available()]);
			imgIs.read(imgData.get(i));
			if (i>0)
				buf.append("\r\n").append(twoHyph).append(boundary).append("\r\n");
			buf.append("Content-Disposition: form-data; name=\"image").append(i+1).append("\"; filename=\"img").append(i+1).append(".jpg\"\r\n");
			buf.append("Content-Type: image/jpeg\r\n\r\n");
			imgCont.add(buf.toString());
		}
		imgCont.add((new StringBuffer("\r\n").append(twoHyph).append(boundary).append(twoHyph)).toString());


		int contentLength=body.length();
		for (int i=0;i<imgCont.size();i++)
			contentLength+=imgCont.get(i).length();
		for (int i=0;i<imgData.size();i++)
			contentLength+=imgData.get(i).length;
		header.append("Content-Length: ").append(String.valueOf(contentLength));
		header.append("\r\n\r\n");
		os.write(header.toString().getBytes());
		os.write(body.toString().getBytes());
		for (int i=0;i<imgData.size();i++){
			os.write(imgCont.get(i).toString().getBytes());
			int index = 0; 
			int size = 3145728; 


			if((index+size)>imgData.get(i).length){ 
				size = imgData.get(i).length - index; 
			} 
			os.write(imgData.get(i), index, size); 

		}
		os.write(imgCont.get(imgCont.size()-1).toString().getBytes());
		os.flush();


		BufferedReader rd = new BufferedReader(new InputStreamReader(socket.getInputStream()));

		//	}
		StringBuffer line=new StringBuffer();
		boolean redirect=false;
		String location="";
		int count=0;
		while (((line=line.append(rd.readLine())) != null)) {
			if (line.indexOf("HTTP/1.1 302 Moved Temporarily")!=-1)
				redirect=true;
			if(redirect==true&&line.indexOf("Location: http")!=-1){
				location=line.substring(line.indexOf("Location: ")+("Location: ").length());
				break;
			}
		}

		System.out.println("LOCATION: "+location);
		if (redirect==true){
			line=doSubmit4(null,location.substring(location.indexOf(runSettings.hostURL.toString())+runSettings.hostURL.length()).replace(" ", "%20"),null,client);
			line=line.delete(0, line.indexOf("<HTML>"));
		}
		System.out.println("DOSUBMITPIC2 RET: "+line);

		os.close();
		rd.close();
		socket.close();
		return line;
	}

	//	/**
	//	 * POSTs pictures to an online form
	//	 * @param url - url of form
	//	 * @param data - HashMap of data to be posted to the form
	//	 * @param pics - ArrayList of files to be posted to the form
	//	 * @return Returns the page returned after form submission
	//	 * @throws org.apache.http.ParseException
	//	 * @throws ClientProtocolException
	//	 * @throws IOException
	//	 * @throws InterruptedException 
	//	 */
	//	public synchronized StringBuffer doSubmitPic(StringBuffer url,HashMap<String, StringBuffer> data,ArrayList<File> pics) throws org.apache.http.ParseException, ClientProtocolException, IOException, InterruptedException{
	//		if(verbose)System.out.println("URL PIC: "+ url);
	//		//	Socket socket=SSLSocketFactory.getDefault().createSocket("10.9.77.3",8080);
	//
	//		PlainSocketFactory sf=PlainSocketFactory.getSocketFactory();
	//		Socket socket=sf.createSocket();
	//		HttpParams params=new BasicHttpParams();
	//		InetSocketAddress address=new InetSocketAddress("10.9.77.3",8080);
	//		//		InetSocketAddress localAddress=new InetSocketAddress("localhost",51234);
	//		sf.connectSocket(socket,address,null,params);
	//
	//		HttpClient client = new DefaultHttpClient();
	//		HttpGet httpget = new HttpGet(url.toString());
	//		HttpPost  post   = new HttpPost( url.toString() );
	//		HttpContext localContext = new BasicHttpContext();
	//		MultipartEntity entity = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE );
	//		client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
	//
	//		for (String m:data.keySet()){
	//			entity.addPart(m,new StringBody(data.get(m).toString()));
	//		}
	//
	//		for (int i=0;i<pics.size();i++){
	//			entity.addPart("image"+i, new FileBody(pics.get(i), "image/jpeg"));
	//		}
	//
	//		post.setEntity(entity);
	//		//	OutputStream outout=null;
	//		//	System.out.println("Entity: "+MultipartEntityUtils.toString(entity));
	//
	//		HttpResponse response = client.execute(post);
	//
	//
	//		InputStream result=null;
	//		org.apache.http.Header locationHeader=response.getFirstHeader("Location");
	//		if (locationHeader != null) {
	//			httpget = new HttpGet(locationHeader.getValue());
	//			response=getThreadSafeClient().execute(httpget);
	//		}
	//
	//		result = response.getEntity().getContent();
	//		stopwatch sw=new stopwatch();
	//		BufferedReader br = new BufferedReader(new InputStreamReader(result));
	//		StringBuffer ret=new StringBuffer();
	//
	//		if(br.read()!=-1){
	//			do{
	//				ret.append(br.readLine());
	//			}while(ret.indexOf("</HTML>")==-1);
	//			sw.pause();
	//			// find image links
	//			//			int end=ret.indexOf(".jpg\"")+".jpg".length();
	//			//			int start=ret.lastIndexOf("\"../",end)+"\"../".length();
	//			//			while(end!=".jpg".length()-1){
	//			//				getImage gI=new getImage(ret.substring(start,end));
	//			//				addConnection();
	//			//				sw.start();
	//			//				gI.start();
	//			//				if (getConnectionCount()==0)
	//			//					sw.pause();
	//			//				end=ret.indexOf(".jpg\"",end)+".jpg".length();
	//			//				start=ret.lastIndexOf("\"../",end)+"\"../".length();
	//			//			}
	//			//			while(getConnectionCount()>0){wait();}
	//			this.responseTime=sw.stop();
	//		}
	//		clientGenerator.stats.activeHistogram.add(responseTime);
	//		result.close();
	//		client.getConnectionManager().shutdown();
	//		System.out.println("RETRETRET "+ ret);
	//		return ret;
	//		//	return locationHeader.getValue();
	//	}
	//
	//
	//	public DefaultHttpClient getThreadSafeClient() {
	//		DefaultHttpClient client = new DefaultHttpClient();
	//		ClientConnectionManager mgr = client.getConnectionManager();
	//		HttpParams params = client.getParams();
	//
	//		client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, 
	//				mgr.getSchemeRegistry()), params);
	//
	//		return client;
	//	}

	/**
	 * Randomly selects a number from an exponential distribution
	 * @param mean - mean of the distribution
	 * @return Random Number from distribution
	 */
	public double expDist(double mean) {
		return (-Math.log(1 - Math.random()) * mean);
	}

	/**
	 * Returns a random string selected from a distribution
	 * @param map - a map of the distribution of form (probability, string)
	 * @return The randomly chosen string
	 */
	public StringBuffer getRandomStringFromDist(TreeMap<Double,StringBuffer> map){
		StringBuffer ret=new StringBuffer();
		double rand=Math.random();
		for(Double m:map.keySet()){
			if (rand<m){
				ret=map.get(m);
				break;
			}
		}
		return new StringBuffer(ret);
	}

	/**
	 * Returns a random integer selected from a distribution
	 * @param map - a map of the distribution of form (probability, integer)
	 * @return The randomly chosen integer
	 */
	public int getRandomIntFromDist(TreeMap<Double,Integer> map){
		int ret=0;
		double rand=Math.random();
		for(Double m:map.keySet()){
			if (rand<m){
				ret=map.get(m);
				break;
			}
		}
		return ret;
	}

	/**
	 * Returns a random double selected from a distribution
	 * @param map - a map of the distribution of form (probability, double)
	 * @return The randomly chosen double
	 */
	public double getRandomDoubleFromDist(TreeMap<Double,Double> map){
		double ret=0;
		double rand=Math.random();
		for(Double m:map.keySet()){
			if (rand<m){
				ret=map.get(m);
				break;
			}
		}
		return ret;
	}

	public class getImage extends Thread{
		String suffix;
		public getImage(String URLsuffix){
			this.suffix=URLsuffix;
		}
		public void run(){
			synchronized(this){
				try {
					ImageIO.read(new URL((runSettings.hostURL.append(suffix)).toString()));
					delConnection();
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

	}

	public synchronized void addConnection(){
		activeConnections+=1;
	}

	public synchronized void delConnection(){
		activeConnections-=1;
		notify();
	}
	public synchronized int getConnectionCount(){
		return activeConnections;
	}


}
